﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MongoDB.Driver;
using Sustainalytics.ClientDW.Entities;
using Sustainalytics.DataLayer.CompanyHistory;
using Sustainalytics.DataLayer.Shared;

namespace Sustainalytics.DataLayer.Tests.CompanyHistory
{
    [TestClass]
    public class CompanyHistoricalPerformanceRepositoryTest
    {
        private const string DbCnx = "mongodb://localhost:27017/ClientPlatform_Tests";
        private IRepositoryCollection<CompanyHistoricalPerformance> _sut;
        private string _databaseName;            
        private readonly Guid _companyGuid = new Guid("c4621c00-af02-4ec6-8399-af1489c9dfc9");
            
        [TestInitialize]
        public void Setup()
        {
            _sut= new CompanyPerformanceHistoryRepository(DbCnx);
            _databaseName = new MongoUrl(DbCnx).DatabaseName;
        }


        [TestMethod]
        public void CompanyPerformance_OneItem_Test()
        {
            var item = _sut.ReadAllWhere(x => x.Id == _companyGuid).FirstOrDefault();

            var itemToInsert = new CompanyHistoricalPerformance
            {
                Id = _companyGuid,
                Last36Months = new List<CompanyHistoryData>
                {
                    new CompanyHistoryData
                    {
                        Date = DateTime.Today,
                        EnvironmentAverage = 2,
                        EnvironmentBestInClass = 2,
                        EnvironmentScore = 2,
                        GovernanceAverage = 2,
                        GovernanceBestInClass = 2,
                        GovernanceScore = 2,
                        CompanyId = _companyGuid,
                        OverallAverage = 2,
                        OverallBestInClass = 2,
                        OverallScore = 2
                    }
                }
            };
            _sut.CreateOrUpdate(itemToInsert);

            var afterInsert = _sut.ReadAllWhere(x => x.Id == _companyGuid).FirstOrDefault();

            Assert.IsTrue(afterInsert != null && afterInsert.Last36Months.Count<=36);
        }


        [TestMethod]
        public void CompanyPerformance_TwoItems_Test()
        {
            var refDate = new DateTime(2015, 05, 11,0,0,0,DateTimeKind.Utc);
           

            var itemToInsert = new CompanyHistoricalPerformance
            {
                Id = _companyGuid,
                Last36Months = new List<CompanyHistoryData>
                {
                    new CompanyHistoryData
                    {
                        Date = GetFirstDayOfMonth(refDate),
                        EnvironmentAverage = 2,
                        EnvironmentBestInClass = 2,
                        EnvironmentScore = 2,
                        GovernanceAverage = 2,
                        GovernanceBestInClass = 2,
                        GovernanceScore = 2,
                        SocialAverage = 2,
                        SocialBestInClass = 2,
                        SocialScore = 2,
                        CompanyId = _companyGuid,
                        OverallAverage = 2,
                        OverallBestInClass = 2,
                        OverallScore = 2
                    },
                    new CompanyHistoryData
                    {
                        Date = GetFirstDayOfMonth(refDate.AddMonths(-1)),
                        EnvironmentAverage = 1,
                        EnvironmentBestInClass = 1,
                        EnvironmentScore = 1,
                        GovernanceAverage = 1,
                        GovernanceBestInClass = 1,
                        GovernanceScore = 1,
                        SocialAverage = 1,
                        SocialBestInClass = 1,
                        SocialScore = 1,
                        CompanyId = _companyGuid,
                        OverallAverage = 1,
                        OverallBestInClass = 1,
                        OverallScore = 1
                    }
                }
            };
            _sut.CreateOrUpdate(itemToInsert);

            var afterInsert = _sut.ReadAllWhere(x => x.Id == _companyGuid).FirstOrDefault();

            Assert.IsTrue(afterInsert != null && afterInsert.Last36Months.Count <= 36);
        }



        [TestMethod]
        public void CompanyPerformance_36Items_Test()
        {
            var refDate = new DateTime(2015, 05, 11, 0, 0, 0, DateTimeKind.Utc);


            var itemToInsert = new CompanyHistoricalPerformance
            {
                Id = _companyGuid,
                Last36Months = Enumerable.Range(0,36).Select(
                x=>new CompanyHistoryData
                    {
                        Date = GetFirstDayOfMonth(refDate.AddMonths(x)),
                        EnvironmentAverage = 2,
                        EnvironmentBestInClass = 2,
                        EnvironmentScore = 2,
                        GovernanceAverage = 2,
                        GovernanceBestInClass = 2,
                        GovernanceScore = 2,
                        SocialAverage = 2,
                        SocialBestInClass = 2,
                        SocialScore = 2,
                        CompanyId = _companyGuid,
                        OverallAverage = 2,
                        OverallBestInClass = 2,
                        OverallScore = 2
                    }).ToList() };

            _sut.CreateOrUpdate(itemToInsert);

            var afterInsert = _sut.ReadAllWhere(x => x.Id == _companyGuid).FirstOrDefault();

            Assert.IsTrue(afterInsert != null && afterInsert.Last36Months.Count == 36);
        }


        [TestMethod]
        public void CompanyPerformance_37Items_Test()
        {



            var refDate = new DateTime(2015, 02, 11, 0, 0, 0, DateTimeKind.Utc);


            var itemToInsert = new CompanyHistoricalPerformance
            {
                Id = _companyGuid,
                Last36Months = Enumerable.Range(0, 37).Select(
                x => new CompanyHistoryData
                {
                    Date = GetFirstDayOfMonth(refDate.AddMonths(x)),
                    EnvironmentAverage = 2,
                    EnvironmentBestInClass = 2,
                    EnvironmentScore = 2,
                    GovernanceAverage = 2,
                    GovernanceBestInClass = 2,
                    GovernanceScore = 2,
                    SocialAverage = 2,
                    SocialBestInClass = 2,
                    SocialScore = 2,
                    CompanyId = _companyGuid,
                    OverallAverage = 2,
                    OverallBestInClass = 2,
                    OverallScore = 2
                }).ToList()
            };

            _sut.Collection().Database.DropCollection(typeof(CompanyHistoricalPerformance).Name);

            var result=_sut.CreateOrUpdate(itemToInsert);

            var afterInsert = _sut.ReadAllWhere(x => x.Id == _companyGuid).FirstOrDefault();

            Assert.IsTrue(afterInsert != null && afterInsert.Last36Months.Count == 36);
        }


        [TestMethod]
        public void CompanyPerformance_With_Two_TimeFrame_Items_And_Overlap_Test()
        {

            var refDate = new DateTime(2014, 02, 11, 0, 0, 0, DateTimeKind.Utc);

            var secondSection = new CompanyHistoricalPerformance
            {
                Id = _companyGuid,
                Last36Months = Enumerable.Range(-9, 36).Select(
                x => new CompanyHistoryData
                {
                    Date = GetFirstDayOfMonth(refDate.AddMonths(x)),
                    EnvironmentAverage = 2,
                    EnvironmentBestInClass = 2,
                    EnvironmentScore = 2,
                    GovernanceAverage = 2,
                    GovernanceBestInClass = 2,
                    GovernanceScore = 2,
                    SocialAverage = 2,
                    SocialBestInClass = 2,
                    SocialScore = 2,
                    CompanyId = _companyGuid,
                    OverallAverage = 2,
                    OverallBestInClass = 2,
                    OverallScore = 2
                }).ToList()
            };

            var firstSection = new CompanyHistoricalPerformance
            {
                Id = _companyGuid,
                Last36Months = Enumerable.Range(-28, 36).Select(
                x => new CompanyHistoryData
                {
                    Date = GetFirstDayOfMonth(refDate.AddMonths(x)),
                    EnvironmentAverage = 1,
                    EnvironmentBestInClass = 1,
                    EnvironmentScore = 1,
                    GovernanceAverage = 1,
                    GovernanceBestInClass = 1,
                    GovernanceScore = 1,
                    SocialAverage = 1,
                    SocialBestInClass = 1,
                    SocialScore = 1,
                    CompanyId = _companyGuid,
                    OverallAverage = 1,
                    OverallBestInClass = 1,
                    OverallScore = 1
                }).ToList()
            };

            _sut.Collection().DeleteMany(_ => true);
            _sut.CreateOrUpdate(firstSection);
             _sut.CreateOrUpdate(secondSection);

            var afterInsert = _sut.ReadAllWhere(x => x.Id == _companyGuid).FirstOrDefault();
            var afterInsertMonths = afterInsert.Last36Months.Select(x => x.Date);
            var expectedResult = Enumerable.Range(-9, 36).Select(x => GetFirstDayOfMonth(refDate.AddMonths(x)));

            Assert.AreEqual(expectedResult,afterInsertMonths);
        }


      


        private DateTime GetFirstDayOfMonth(DateTime refDate)
        {
            return new DateTime(refDate.Year,refDate.Month,1,0,0,0,DateTimeKind.Utc);
        }
    }
}